/* * Copyright (c) 2005-2016 Vincent Vandenschrick. All rights reserved. * * This file is part of the Jspresso framework. * * Jspresso is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Jspresso is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Jspresso. If not, see <http://www.gnu.org/licenses/>. */ package org.jspresso.framework.application.frontend.controller.swing; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Frame; import java.awt.Insets; import java.awt.Toolkit; import java.awt.Window; import java.awt.datatransfer.Clipboard; import java.awt.event.KeyAdapter; import java.awt.event.MouseAdapter; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.beans.PropertyVetoException; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.TimeZone; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; import javax.swing.Action; import javax.swing.BorderFactory; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JDesktopPane; import javax.swing.JDialog; import javax.swing.JFrame; import javax.swing.JInternalFrame; import javax.swing.JLabel; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JSplitPane; import javax.swing.JToolBar; import javax.swing.SwingUtilities; import javax.swing.WindowConstants; import javax.swing.border.EmptyBorder; import javax.swing.border.EtchedBorder; import javax.swing.event.InternalFrameAdapter; import javax.swing.event.InternalFrameEvent; import chrriis.dj.nativeswing.swtimpl.components.FlashPluginOptions; import chrriis.dj.nativeswing.swtimpl.components.JFlashPlayer; import chrriis.dj.swingsuite.JComboButton; import org.jspresso.framework.action.ActionContextConstants; import org.jspresso.framework.action.ActionException; import org.jspresso.framework.action.IAction; import org.jspresso.framework.application.ControllerException; import org.jspresso.framework.application.backend.BackendControllerHolder; import org.jspresso.framework.application.backend.IBackendController; import org.jspresso.framework.application.frontend.controller.AbstractFrontendController; import org.jspresso.framework.application.model.Module; import org.jspresso.framework.binding.IValueConnector; import org.jspresso.framework.gui.swing.components.JErrorDialog; import org.jspresso.framework.util.gui.Dimension; import org.jspresso.framework.util.gui.EClientType; import org.jspresso.framework.util.html.HtmlHelper; import org.jspresso.framework.util.lang.ObjectUtils; import org.jspresso.framework.util.preferences.IPreferencesStore; import org.jspresso.framework.util.preferences.JavaPreferencesStore; import org.jspresso.framework.util.security.LoginUtils; import org.jspresso.framework.util.swing.BrowserControl; import org.jspresso.framework.util.swing.SwingUtil; import org.jspresso.framework.util.swing.WaitCursorEventQueue; import org.jspresso.framework.util.swing.WaitCursorTimer; import org.jspresso.framework.util.url.UrlHelper; import org.jspresso.framework.view.IView; import org.jspresso.framework.view.action.ActionList; import org.jspresso.framework.view.action.IDisplayableAction; import org.jspresso.framework.view.descriptor.IViewDescriptor; import org.jspresso.framework.view.swing.BasicTransferable; /** * This is is the default implementation of the <b>Swing</b> frontend * controller. It will implement a 2-tier architecture that is particularly * useful for the development/debugging phases. Workspaces are displayed using * an MDI UI using internal frames. * * @author Vincent Vandenschrick */ public class DefaultSwingController extends AbstractFrontendController<JComponent, Icon, Action> { public static final String CIRCLE_GREY_PNG = "circle_grey-24x24.png"; public static final String CIRCLE_GREEN_PNG = "circle_green-24x24.png"; private JFrame controllerFrame; private JDesktopPane desktopPane; private JLabel statusBar; private WaitCursorTimer waitTimer; private Map<String, JInternalFrame> workspaceInternalFrames; private JDialog loginDialog; private ScheduledExecutorService timerService; private ScheduledFuture<?> currentActionTimer; private ImageIcon repeatGreyStatusIcon = new ImageIcon(getClass().getResource(CIRCLE_GREY_PNG)); private ImageIcon repeatGeenStatusIcon = new ImageIcon(getClass().getResource(CIRCLE_GREEN_PNG)); private JLabel repeatStatusLabel = new JLabel(repeatGreyStatusIcon); /** * {@inheritDoc} */ @Override public void displayFlashObject(String swfUrl, Map<String, String> flashContext, List<Action> actions, String title, JComponent sourceComponent, Map<String, Object> context, Dimension dimension, boolean reuseCurrent) { JFlashPlayer flashPlayer = new JFlashPlayer(); FlashPluginOptions options = new FlashPluginOptions(); options.setVariables(flashContext); flashPlayer.load(getClass(), UrlHelper.getResourcePathOrUrl(swfUrl, true), options); displayDialog(flashPlayer, actions, title, sourceComponent, context, dimension, reuseCurrent, false); } /** * {@inheritDoc} */ @Override public void displayDialog(final JComponent mainView, final List<Action> actions, final String title, final JComponent sourceComponent, final Map<String, Object> context, final Dimension dimension, final boolean reuseCurrent, final boolean modal) { cancelCurrentActionTimer(); displayModalDialog(mainView, context, reuseCurrent); SwingUtilities.invokeLater(new Runnable() { @Override public void run() { JDialog dialog; Window window; if (sourceComponent != null) { window = SwingUtil.getVisibleWindow(sourceComponent); } else { window = controllerFrame; } boolean newDialog = true; if (window instanceof JDialog) { if (reuseCurrent) { dialog = (JDialog) window; dialog.getContentPane().removeAll(); newDialog = false; } else { dialog = new JDialog((JDialog) window, title, modal); } } else { dialog = new JDialog((Frame) window, title, modal); } Box buttonBox = new Box(BoxLayout.LINE_AXIS); buttonBox.setBorder(new EmptyBorder(new Insets(5, 10, 5, 10))); JButton defaultButton = null; for (Action action : actions) { JButton actionButton = new JButton(); SwingUtil.configureButton(actionButton); actionButton.setAction(action); buttonBox.add(actionButton); buttonBox.add(Box.createHorizontalStrut(10)); if (defaultButton == null) { defaultButton = actionButton; } } JPanel actionPanel = new JPanel(); actionPanel.setLayout(new BorderLayout()); actionPanel.add(buttonBox, BorderLayout.EAST); if (dimension != null) { mainView.setPreferredSize(new java.awt.Dimension(dimension.getWidth(), dimension.getHeight())); } JPanel mainPanel = new JPanel(); mainPanel.setLayout(new BorderLayout()); mainPanel.add(mainView, BorderLayout.CENTER); mainPanel.add(actionPanel, BorderLayout.SOUTH); dialog.getContentPane().add(mainPanel); dialog.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); if (defaultButton != null) { dialog.getRootPane().setDefaultButton(defaultButton); } dialog.pack(); if (newDialog) { SwingUtil.centerInParent(dialog); } dialog.setVisible(true); } }); } /** * {@inheritDoc} */ @Override public void displayUrl(String urlSpec, String target) { try { BrowserControl.displayURL(urlSpec); } catch (IOException ex) { throw new ActionException(ex); } } /** * {@inheritDoc} */ @Override protected void displayWorkspace(String workspaceName, boolean bypassModuleBoundaryActions) { if (!ObjectUtils.equals(workspaceName, getSelectedWorkspaceName())) { cancelCurrentActionTimer(); super.displayWorkspace(workspaceName, bypassModuleBoundaryActions); if (workspaceName != null) { if (workspaceInternalFrames == null) { workspaceInternalFrames = new HashMap<>(); } JInternalFrame workspaceInternalFrame = workspaceInternalFrames.get(workspaceName); if (workspaceInternalFrame == null) { IViewDescriptor workspaceNavigatorViewDescriptor = getWorkspace(workspaceName).getViewDescriptor(); IValueConnector workspaceConnector = getBackendController().getWorkspaceConnector(workspaceName); IView<JComponent> workspaceNavigator = createWorkspaceNavigator(workspaceName, workspaceNavigatorViewDescriptor); IView<JComponent> moduleAreaView = createModuleAreaView(workspaceName); JSplitPane workspaceView = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); workspaceView.setOneTouchExpandable(true); workspaceView.add(workspaceNavigator.getPeer()); workspaceView.add(moduleAreaView.getPeer()); workspaceInternalFrame = createJInternalFrame( workspaceView, workspaceNavigatorViewDescriptor.getI18nName(this, getLocale()), getIconFactory().getIcon( workspaceNavigatorViewDescriptor.getIcon(), getIconFactory().getSmallIconSize())); workspaceInternalFrame .addInternalFrameListener(new WorkspaceInternalFrameListener( workspaceName)); workspaceInternalFrames.put(workspaceName, workspaceInternalFrame); desktopPane.add(workspaceInternalFrame); getMvcBinder().bind(workspaceNavigator.getConnector(), workspaceConnector); workspaceInternalFrame.pack(); workspaceInternalFrame.setSize(controllerFrame.getWidth() - 50, controllerFrame.getHeight() - 50); try { workspaceInternalFrame.setMaximum(true); } catch (PropertyVetoException ex) { throw new ControllerException(ex); } } workspaceInternalFrame.setVisible(true); if (workspaceInternalFrame.isIcon()) { try { workspaceInternalFrame.setIcon(false); } catch (PropertyVetoException ex) { throw new ControllerException(ex); } } workspaceInternalFrame.toFront(); } } updateFrameTitle(); } /** * {@inheritDoc} */ @Override public void displayModule(String workspaceName, Module module) { cancelCurrentActionTimer(); super.displayModule(workspaceName, module); } /** * {@inheritDoc} */ @Override public boolean disposeModalDialog(JComponent sourceWidget, Map<String, Object> context) { if (super.disposeModalDialog(sourceWidget, context)) { Window actionWindow = SwingUtil.getVisibleWindow(sourceWidget); if (actionWindow instanceof JDialog) { actionWindow.dispose(); } transferFocus(context); return true; } return false; } /** * {@inheritDoc} */ @Override public boolean execute(final IAction action, final Map<String, Object> context) { if (action == null) { return true; } if (action instanceof IDisplayableAction) { Integer repeatPeriodMillis = ((IDisplayableAction) action).getRepeatPeriodMillis(); if(repeatPeriodMillis != null && repeatPeriodMillis > 0) { repeatStatusLabel.setIcon(repeatGeenStatusIcon); currentActionTimer = timerService.scheduleWithFixedDelay(new Runnable() { @Override public void run() { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { doExecute(action, context); } } ); } }, 0, repeatPeriodMillis, TimeUnit.MILLISECONDS); return true; } } return doExecute(action, context); } public void cancelCurrentActionTimer() { if (currentActionTimer != null) { repeatStatusLabel.setIcon(repeatGreyStatusIcon); currentActionTimer.cancel(false); } } private boolean doExecute(IAction action, Map<String, Object> context) { JComponent sourceComponent = (JComponent) context.get(ActionContextConstants.SOURCE_COMPONENT); Component windowOrInternalFrame = null; if (sourceComponent != null) { windowOrInternalFrame = SwingUtil.getWindowOrInternalFrame(sourceComponent); } if (windowOrInternalFrame instanceof JFrame) { ((JFrame) windowOrInternalFrame).getGlassPane().setVisible(true); } else if (windowOrInternalFrame instanceof JInternalFrame) { ((JInternalFrame) windowOrInternalFrame).getGlassPane().setVisible(true); } else if (windowOrInternalFrame instanceof JDialog) { ((JDialog) windowOrInternalFrame).getGlassPane().setVisible(true); } waitTimer.startTimer(sourceComponent); try { return super.execute(action, context); } finally { if (windowOrInternalFrame instanceof JFrame) { ((JFrame) windowOrInternalFrame).getGlassPane().setVisible(false); } else if (windowOrInternalFrame instanceof JInternalFrame) { ((JInternalFrame) windowOrInternalFrame).getGlassPane().setVisible(false); } else if (windowOrInternalFrame instanceof JDialog) { ((JDialog) windowOrInternalFrame).getGlassPane().setVisible(false); } waitTimer.stopTimer(); } } /** * {@inheritDoc} */ @Override public boolean handleException(Throwable ex, Map<String, Object> context) { if (super.handleException(ex, context)) { return true; } String userFriendlyExceptionMessage = computeUserFriendlyExceptionMessage(ex); Component sourceComponent = controllerFrame; if (userFriendlyExceptionMessage != null) { JOptionPane.showMessageDialog(sourceComponent, HtmlHelper .toHtml(HtmlHelper.emphasis(HtmlHelper .escapeForHTML(userFriendlyExceptionMessage))), getTranslation("error", getLocale()), JOptionPane.ERROR_MESSAGE, getIconFactory().getErrorIcon(getIconFactory().getLargeIconSize())); } else { traceUnexpectedException(ex); JErrorDialog dialog = JErrorDialog.createInstance(sourceComponent, this, getLocale()); dialog.setMessageIcon(getIconFactory().getErrorIcon( getIconFactory().getMediumIconSize())); dialog.setTitle(getTranslation("error", getLocale())); dialog.setMessage(HtmlHelper.toHtml(HtmlHelper.emphasis(HtmlHelper .escapeForHTML(ex.getLocalizedMessage())))); dialog.setDetails(ex); int screenRes = Toolkit.getDefaultToolkit().getScreenResolution(); dialog.pack(); dialog.setSize(8 * screenRes, 3 * screenRes); SwingUtil.centerOnScreen(dialog); dialog.setVisible(true); } return true; } /** * {@inheritDoc} */ @Override public void popupInfo(final JComponent sourceComponent, final String title, final String iconImageUrl, final String message) { // To have the same threading model than the other UI channels SwingUtilities.invokeLater(new Runnable() { @Override public void run() { JOptionPane.showMessageDialog( SwingUtil.getWindowOrInternalFrame(sourceComponent), message, title, JOptionPane.INFORMATION_MESSAGE, getIconFactory().getIcon(iconImageUrl, getIconFactory().getLargeIconSize())); } }); } /** * {@inheritDoc} */ @Override public void popupOkCancel(final JComponent sourceComponent, final String title, final String iconImageUrl, final String message, final IAction okAction, final IAction cancelAction, final Map<String, Object> context) { // To have the same threading model than the other UI channels SwingUtilities.invokeLater(new Runnable() { @Override public void run() { int selectedOption = JOptionPane.showConfirmDialog( SwingUtil.getWindowOrInternalFrame(sourceComponent), message, title, JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE, getIconFactory().getIcon(iconImageUrl, getIconFactory().getLargeIconSize())); IAction nextAction; if (selectedOption == JOptionPane.OK_OPTION) { nextAction = okAction; } else { nextAction = cancelAction; } if (nextAction != null) { execute(nextAction, context); } } }); } /** * {@inheritDoc} */ @Override public void popupYesNo(final JComponent sourceComponent, final String title, final String iconImageUrl, final String message, final IAction yesAction, final IAction noAction, final Map<String, Object> context) { // To have the same threading model than the other UI channels SwingUtilities.invokeLater(new Runnable() { @Override public void run() { int selectedOption = JOptionPane.showConfirmDialog( SwingUtil.getWindowOrInternalFrame(sourceComponent), message, title, JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, getIconFactory().getIcon(iconImageUrl, getIconFactory().getLargeIconSize())); IAction nextAction; if (selectedOption == JOptionPane.YES_OPTION) { nextAction = yesAction; } else { nextAction = noAction; } if (nextAction != null) { execute(nextAction, context); } } }); } /** * {@inheritDoc} */ @Override public void popupYesNoCancel(final JComponent sourceComponent, final String title, final String iconImageUrl, final String message, final IAction yesAction, final IAction noAction, final IAction cancelAction, final Map<String, Object> context) { // To have the same threading model than the other UI channels SwingUtilities.invokeLater(new Runnable() { @Override public void run() { int selectedOption = JOptionPane.showConfirmDialog( SwingUtil.getWindowOrInternalFrame(sourceComponent), message, title, JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, getIconFactory().getIcon(iconImageUrl, getIconFactory().getLargeIconSize())); IAction nextAction; if (selectedOption == JOptionPane.YES_OPTION) { nextAction = yesAction; } else if (selectedOption == JOptionPane.NO_OPTION) { nextAction = noAction; } else { nextAction = cancelAction; } if (nextAction != null) { execute(nextAction, context); } } }); } /** * Creates the initial view from the root view descriptor, then a SFrame * containing this view and presents it to the user. * <p> * {@inheritDoc} */ @Override public boolean start(final IBackendController backendController, Locale clientLocale, TimeZone clientTimeZone) { if (super.start(backendController, clientLocale, clientTimeZone)) { waitTimer = new WaitCursorTimer(500); waitTimer.setDaemon(true); waitTimer.start(); Toolkit.getDefaultToolkit().getSystemEventQueue() .push(new WaitCursorEventQueue(500)); Toolkit.getDefaultToolkit().setDynamicLayout(true); getApplicationSession().setClientType(EClientType.DESKTOP_SWING); SwingUtilities.invokeLater(new Runnable() { @Override public void run() { // To register the backend controller in the event dispatch thread BackendControllerHolder.setSessionBackendController(backendController); initLoginProcess(); } }); timerService = Executors.newSingleThreadScheduledExecutor(); return true; } return false; } /** * {@inheritDoc} */ @Override public boolean stop() { if (super.stop()) { cancelCurrentActionTimer(); timerService.shutdown(); if (controllerFrame != null) { controllerFrame.dispose(); } System.exit(0); return true; } return false; } private JToolBar createApplicationToolBar() { JToolBar applicationToolBar = new JToolBar(); applicationToolBar.setRollover(true); applicationToolBar.setFloatable(false); if (getWorkspaceNames() != null && !getWorkspaceNames().isEmpty()) { applicationToolBar.add(createComboButton(createWorkspaceActionList())); } applicationToolBar.addSeparator(); if (getNavigationActions() != null && isAccessGranted(getNavigationActions())) { try { pushToSecurityContext(getNavigationActions()); for (ActionList actionList : getNavigationActions() .getActionLists(this)) { completeApplicationToolBar(applicationToolBar, actionList); } } finally { restoreLastSecurityContextSnapshot(); } } if (getActionMap() != null && isAccessGranted(getActionMap())) { try { pushToSecurityContext(getActionMap()); for (ActionList actionList : getActionMap().getActionLists(this)) { completeApplicationToolBar(applicationToolBar, actionList); } } finally { restoreLastSecurityContextSnapshot(); } } applicationToolBar.add(Box.createHorizontalGlue()); applicationToolBar.add(repeatStatusLabel); applicationToolBar.add(Box.createHorizontalStrut(5)); if (getHelpActions() != null && isAccessGranted(getHelpActions())) { try { pushToSecurityContext(getHelpActions()); for (ActionList actionList : getHelpActions().getActionLists(this)) { completeApplicationToolBar(applicationToolBar, actionList); } } finally { restoreLastSecurityContextSnapshot(); } } JButton exitButton = new JButton(); exitButton.setAction(getViewFactory().getActionFactory().createAction( getExitAction(), this, null, getLocale())); applicationToolBar.add(exitButton); return applicationToolBar; } private JToolBar createSecondaryApplicationToolBar() { JToolBar applicationToolBar = new JToolBar(); applicationToolBar.setRollover(true); applicationToolBar.setFloatable(false); if (getSecondaryActionMap() != null) { for (ActionList actionList : getSecondaryActionMap().getActionLists(this)) { completeApplicationToolBar(applicationToolBar, actionList); } } return applicationToolBar; } private void completeApplicationToolBar(JToolBar applicationToolBar, ActionList actionList) { if (isAccessGranted(actionList)) { try { pushToSecurityContext(actionList); if (actionList.isCollapsable()) { applicationToolBar.add(createComboButton(actionList)); } else { for (IDisplayableAction da : actionList.getActions()) { if (isAccessGranted(da)) { JButton b = new JButton(); b.setAction(getViewFactory().getActionFactory().createAction(da, this, null, getLocale())); applicationToolBar.add(b); } } } applicationToolBar.addSeparator(); } finally { restoreLastSecurityContextSnapshot(); } } } private void createControllerFrame() { controllerFrame = new JFrame(); desktopPane = new JDesktopPane(); controllerFrame.getContentPane().add(desktopPane, BorderLayout.CENTER); statusBar = new JLabel(); statusBar.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED)); statusBar.setVisible(false); controllerFrame.getContentPane().add(statusBar, BorderLayout.SOUTH); controllerFrame .setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); controllerFrame.setGlassPane(createHermeticGlassPane()); controllerFrame.addWindowListener(new WindowAdapter() { /** * {@inheritDoc} */ @Override public void windowClosing(WindowEvent e) { execute(getExitAction(), new HashMap<String, Object>()); } }); controllerFrame.pack(); int screenRes = Toolkit.getDefaultToolkit().getScreenResolution(); int w = 12 * screenRes; int h = 8 * screenRes; if (getFrameWidth() != null) { w = getFrameWidth(); } if (getFrameHeight() != null) { h = getFrameHeight(); } controllerFrame.setSize(w, h); // controllerFrame.setSize(1100, 800); ImageIcon frameIcon = ((ImageIcon) getIconFactory().getIcon(getIcon(), getIconFactory().getSmallIconSize())); if (frameIcon != null) { controllerFrame.setIconImage(frameIcon.getImage()); } SwingUtil.centerOnScreen(controllerFrame); updateFrameTitle(); controllerFrame.setVisible(true); } private JComponent createHermeticGlassPane() { JPanel glassPane = new JPanel(); glassPane.setOpaque(false); glassPane.addMouseListener(new MouseAdapter() { // No-op }); glassPane.addKeyListener(new KeyAdapter() { // No-op }); return glassPane; } /** * Creates a new JInternalFrame and populates it with a view. * * @param view * the view to be set into the internal frame. * @return the constructed internal frame. */ private JInternalFrame createJInternalFrame(JComponent view, String title, Icon frameIcon) { JInternalFrame internalFrame = new JInternalFrame(title); internalFrame.setFrameIcon(frameIcon); internalFrame.setResizable(true); internalFrame.setClosable(true); internalFrame.setMaximizable(true); internalFrame.setIconifiable(true); internalFrame.getContentPane().add(view, BorderLayout.CENTER); internalFrame.setDefaultCloseOperation(WindowConstants.HIDE_ON_CLOSE); internalFrame.setGlassPane(createHermeticGlassPane()); return internalFrame; } private JMenuItem createMenuItem(IDisplayableAction action) { return new JMenuItem(getViewFactory().getActionFactory().createAction( action, this, null, getLocale())); } private JButton createComboButton(ActionList actionList) { JButton button; List<IDisplayableAction> actions = new ArrayList<>(); for (IDisplayableAction action : actionList.getActions()) { if (isAccessGranted(action)) { try { pushToSecurityContext(action); actions.add(action); } finally { restoreLastSecurityContextSnapshot(); } } } if (actions.isEmpty()) { return null; } if (actions.size() > 1) { button = new JComboButton(true); } else { button = new JButton(); } Action action = getViewFactory().getActionFactory().createAction( actionList.getActions().get(0), this, null, getLocale()); button.setAction(action); if (actions.size() > 1) { JPopupMenu popupMenu = new JPopupMenu(); for (IDisplayableAction menuAction : actions) { popupMenu.add(createMenuItem(menuAction)); } ((JComboButton) button).setArrowPopupMenu(popupMenu); } return button; } private void initLoginProcess() { createControllerFrame(); if (isLoginInteractive()) { IView<JComponent> loginView = createLoginView(); // Login dialog IViewDescriptor loginViewDescriptor = getLoginViewDescriptor(); loginDialog = new JDialog(controllerFrame, loginViewDescriptor.getI18nName(this, getLocale()), true); loginDialog.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); JPanel buttonBox = new JPanel(); buttonBox.setLayout(new BoxLayout(buttonBox, BoxLayout.X_AXIS)); buttonBox.setBorder(new EmptyBorder(new Insets(5, 10, 5, 10))); int i = 0; for (ActionList actionList : loginViewDescriptor.getActionMap().getActionLists(this)) { for (IDisplayableAction action : actionList.getActions()) { JButton button = new JButton(getViewFactory().getActionFactory().createAction(action, getViewFactory().getIconFactory().getSmallIconSize(), this, loginView, getLocale())); buttonBox.add(button); if (i == 0) { loginDialog.getRootPane().setDefaultButton(button); } i++; } } JButton exitButton = new JButton(); exitButton.setAction(getViewFactory().getActionFactory().createAction(getExitAction(), this, null, getLocale())); exitButton.setIcon(getIconFactory().getCancelIcon(getIconFactory().getSmallIconSize())); buttonBox.add(exitButton); JPanel actionPanel = new JPanel(new BorderLayout()); actionPanel.add(buttonBox, BorderLayout.EAST); JPanel mainPanel = new JPanel(new BorderLayout()); mainPanel.add(new JLabel(loginViewDescriptor.getI18nDescription(this, getLocale())), BorderLayout.NORTH); mainPanel.add(loginView.getPeer(), BorderLayout.CENTER); mainPanel.add(actionPanel, BorderLayout.SOUTH); loginDialog.add(mainPanel); loginDialog.pack(); SwingUtil.centerInParent(loginDialog); loginDialog.setVisible(true); } else { performLogin(); updateControllerFrame(); execute(getStartupAction(), getInitialActionContext()); } } /** * Login to the application. */ @Override public void login() { if (performLogin()) { loginDialog.dispose(); updateControllerFrame(); execute(getStartupAction(), getStartupActionContext()); } else { loginFailed(loginDialog); } } /** * Callback after a failed login. * * @param dialog * the login dialog if any. */ protected void loginFailed(JDialog dialog) { if (dialog != null) { JOptionPane.showMessageDialog(dialog, getTranslation(LoginUtils.LOGIN_FAILED, getLocale()), getTranslation("error", getLocale()), JOptionPane.ERROR_MESSAGE); } } private void updateControllerFrame() { // controllerFrame.setJMenuBar(createApplicationMenuBar()); controllerFrame.getContentPane().add(createApplicationToolBar(), BorderLayout.NORTH); if (getSecondaryActionMap() != null && isAccessGranted(getSecondaryActionMap())) { try { pushToSecurityContext(getSecondaryActionMap()); controllerFrame.getContentPane().add( createSecondaryApplicationToolBar(), BorderLayout.SOUTH); } finally { restoreLastSecurityContextSnapshot(); } } controllerFrame.invalidate(); controllerFrame.validate(); updateFrameTitle(); } private void updateFrameTitle() { String workspaceName = getSelectedWorkspaceName(); if (workspaceName != null) { controllerFrame.setTitle(getSelectedWorkspace() .getViewDescriptor().getI18nDescription(this, getLocale()) + " - " + getI18nName(this, getLocale())); } else { controllerFrame.setTitle(getI18nName(this, getLocale())); } } private final class WorkspaceInternalFrameListener extends InternalFrameAdapter { private final String workspaceName; /** * Constructs a new {@code WorkspaceInternalFrameListener} instance. * * @param workspaceName * the workspace identifier this listener is attached to. */ public WorkspaceInternalFrameListener(String workspaceName) { this.workspaceName = workspaceName; } /** * {@inheritDoc} */ @Override public void internalFrameActivated(InternalFrameEvent e) { displayWorkspace(workspaceName); } /** * {@inheritDoc} */ @Override public void internalFrameClosed(InternalFrameEvent e) { displayWorkspace(null); } /** * {@inheritDoc} */ @Override public void internalFrameClosing(InternalFrameEvent e) { displayWorkspace(null); } /** * {@inheritDoc} */ @Override public void internalFrameDeactivated(InternalFrameEvent e) { // displayWorkspace(null); } /** * {@inheritDoc} */ @Override public void internalFrameDeiconified(InternalFrameEvent e) { displayWorkspace(workspaceName); } /** * {@inheritDoc} */ @Override public void internalFrameIconified(InternalFrameEvent e) { // displayWorkspace(null); } /** * {@inheritDoc} */ @Override public void internalFrameOpened(InternalFrameEvent e) { displayWorkspace(workspaceName); } } /** * {@inheritDoc} */ @Override public void setStatusInfo(String statusInfo) { if (statusInfo != null && statusInfo.length() > 0) { statusBar.setText(statusInfo); statusBar.setVisible(true); } else { statusBar.setVisible(false); } } /** * Returns a preference store based pon Java preferences API. * <p> * {@inheritDoc} */ @Override protected IPreferencesStore createClientPreferencesStore() { return new JavaPreferencesStore(); } /** * {@inheritDoc} */ @Override public void setClipboardContent(String plainContent, String htmlContent) { Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard(); BasicTransferable dataTransferObject = new BasicTransferable(plainContent, htmlContent); cb.setContents(dataTransferObject, dataTransferObject); } /** * {@inheritDoc} */ @Override public void setName(String name) { super.setName(name); if (isStarted()) { updateFrameTitle(); } } /** * {@inheritDoc} */ @Override public void notifyApplicationDescriptionChange() { updateFrameTitle(); } }